#include "Shader.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

Shader::Shader(void)
{
// 	GLfloat light_diff[]={1.0f,1.0f,1.0f,1.0f};
// 	GLfloat light_ambi[]={0.0f,0.0f,0.0f,1.0f};
// 	GLfloat light_spec[]={1.0f,1.0f,1.0f,1.0f};
// 	GLfloat light_pos[]={1.0f,0.5f,1.0f,0.0f};
// 
// 	glLightfv(GL_LIGHT0,GL_DIFFUSE,light_diff);
// 	glLightfv(GL_LIGHT0,GL_AMBIENT,light_ambi);	
// 	glLightfv(GL_LIGHT0,GL_SPECULAR,light_spec);
// 	glLightfv(GL_LIGHT0,GL_POSITION,light_pos);
}

Shader::~Shader(void)
{
}

void Shader::GlewInit()
{
	GLenum err = glewInit();
	if (GLEW_OK != err)
	{
		fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
		exit(0);
	}
	fprintf(stdout, "Status: Using GLEW %s\n", glewGetString(GLEW_VERSION));

	// check shader
	// ARB
	if (GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader)
		printf("Ready for GLSL (ARB)\n");
	else 
	{
		printf("No GLSL support\n");
		exit(0);
	}
	//OpenGL 2.0
	if (glewIsSupported("GL_VERSION_4_2"))
		printf("Ready for OpenGL 4.2\n");
	else {
		printf("OpenGL 4.2 not supported\n");
		exit(0);
	}
}

void Shader::SetShaders(char* v_shader, char* f_shader)
{
	char *vs = NULL,*fs = NULL,*fs2 = NULL;

	v = glCreateShader(GL_VERTEX_SHADER);
	f = glCreateShader(GL_FRAGMENT_SHADER);
	f2 = glCreateShader(GL_FRAGMENT_SHADER);

	vs = textFileRead(v_shader);
	fs = textFileRead(f_shader);

	const char * vv = vs;
	const char * ff = fs;

	glShaderSource(v, 1, &vv,NULL);
	glShaderSource(f, 1, &ff,NULL);

	free(vs);free(fs);

	glCompileShader(v);
	glCompileShader(f);

	printShaderInfoLog(v);
	printShaderInfoLog(f);
	printShaderInfoLog(f2);


	p = glCreateProgram();
	glAttachShader(p,v);
	glAttachShader(p,f);

	glLinkProgram(p);
	printProgramInfoLog(p);

	glUseProgram(p);

	// 	glEnableClientState(GL_VERTEX_ARRAY);
	// 	glVertexPointer(2,GL_FLOAT,0,vertices);
	// 	loc = glGetAttribLocation(p,"height");
	// 	glEnableVertexAttribArray(loc);
	// 	glVertexAttribPointer(loc,1,GL_FLOAT,0,0,heights);

	// 	GLint loc1,loc2,loc3,loc4;
	// 	float specIntensity = 0.98;
	// 	float sc[4] = {0.8,0.8,0.8,1.0};
	// 	float threshold[2] = {0.5,0.25};
	// 	float colors[12] = {0.4,0.4,0.8,1.0,
	// 		0.2,0.2,0.4,1.0,
	// 		0.1,0.1,0.1,1.0};
	// 
	// 	loc1 = glGetUniformLocation(p,"specIntensity");
	// 	glUniform1f(loc1,specIntensity);
	// 
	// 	loc2 = glGetUniformLocation(p,"specColor");
	// 	glUniform4f(loc2,sc[0],sc[1],sc[2],sc[3]);
	// 
	// 	loc3 = glGetUniformLocation(p,"t");
	// 	glUniform1fv(loc3,2,threshold);
	// 
	// 	loc4 = glGetUniformLocation(p,"colors");
	// 	glUniform4fv(loc4,3,colors);
}

void Shader::printShaderInfoLog(GLuint obj)
{
	int infologLength = 0;
	int charsWritten  = 0;
	char *infoLog;

	glGetShaderiv(obj, GL_INFO_LOG_LENGTH,&infologLength);

	if (infologLength > 0)
	{
		infoLog = (char *)malloc(infologLength);
		glGetShaderInfoLog(obj, infologLength, &charsWritten, infoLog);
		printf("%s\n",infoLog);
		free(infoLog);
	}
}
void Shader::printProgramInfoLog(GLuint obj)
{
	int infologLength = 0;
	int charsWritten  = 0;
	char *infoLog;

	glGetProgramiv(obj, GL_INFO_LOG_LENGTH,&infologLength);

	if (infologLength > 0)
	{
		infoLog = (char *)malloc(infologLength);
		glGetProgramInfoLog(obj, infologLength, &charsWritten, infoLog);
		printf("%s\n",infoLog);
		free(infoLog);
	}
}

char* Shader::textFileRead( char *fn )
{
	FILE *fp;
	char *content = NULL;

	int count=0;

	if (fn != NULL) {
		fopen_s(&fp,fn,"rt");

		if (fp != NULL) {

			fseek(fp, 0, SEEK_END);
			count = ftell(fp);
			rewind(fp);

			if (count > 0) {
				content = (char *)malloc(sizeof(char) * (count+1));
				count = fread(content,sizeof(char),count,fp);
				content[count] = '\0';
			}
			fclose(fp);
		}
	}
	return content;
}
int Shader::textFileWrite( char *fn, char *s )
{
	FILE *fp;
	int status = 0;

	if (fn != NULL) {
		fopen_s(&fp,fn,"rt");

		if (fp != NULL) {

			if (fwrite(s,sizeof(char),strlen(s),fp) == strlen(s))
				status = 1;
			fclose(fp);
		}
	}
	return(status);
}

